//
//  YZApplyFriendVC.m
//  VET
//
//  Created by lixiaoyi on 2018/7/13.
//  Copyright © 2018年 YZ. All rights reserved.
//

#import "YZApplyFriendVC.h"
#import "ChatHeader.h"
#import "YZFriendApplyCell.h"
#import "ClientSocket.h"
#import "YZChatUtils.h"
#import "varint.h"
#import "YZUser.h"
#import "YZFriendVM.h"
#import "YZNetworkConfig.h"

static NSString *flagCell = @"YZFriendApplyCell";

@interface YZApplyFriendVC ()<UITableViewDelegate,UITableViewDataSource,ClientSocketDelegate> {
    @private UIButton *sendBtn;
}

@property (nonatomic, strong) UITableView *applyFriendTable;

// 所有接收到的数据大小
@property (nonatomic) NSUInteger allSize;

// 所有接收到的数据
@property (nonatomic, strong) NSMutableData *allData;

// 待读字节
@property (nonatomic) unsigned long long bufferSize;

// 缓冲区
@property (nonatomic, strong) NSMutableData *buffer;

/**
 输入的验证申请文本
 */
@property (nonatomic, strong) NSString *inpuString;

/**
 VM
 */
@property (nonatomic, strong) YZFriendVM *friendVM;


@end

@implementation YZApplyFriendVC

#pragma mark - life cycle

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    // title
    self.title = @"验证申请";
    
    // right btn
    sendBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [sendBtn setFrame:CGRectMake(0, 0, 36, 25)];
    [sendBtn setTitle:@"发送" forState:UIControlStateNormal];
    [sendBtn setTitleColor: XZRGB(0x32BE60) forState:UIControlStateNormal];
    [sendBtn.titleLabel setFont:[UIFont systemFontOfSize:17]];
    [sendBtn addTarget:self action:@selector(sendApply:) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *rightBarItem = [[UIBarButtonItem alloc] initWithCustomView:sendBtn];
    self.navigationItem.rightBarButtonItem = rightBarItem;
    
    [self.view addSubview:self.applyFriendTable];
    
    // 待读字节数
    _bufferSize = 0;
    
    // 缓冲区
    _buffer = [NSMutableData data];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // 打开导航
    [self.navigationController setNavigationBarHidden:NO animated:NO];
    
    [ClientSocket shareSocket].socketHost = [YZNetworkConfig getImDomain][@"ip"];
    [ClientSocket shareSocket].socketPort = [[YZNetworkConfig getImDomain][@"port"] integerValue];
    [[ClientSocket shareSocket] autoConnection];
    [ClientSocket shareSocket].socketDelegate = self;
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    // 隐藏导航
    [self.navigationController setNavigationBarHidden:YES animated:NO];
    
    [ClientSocket shareSocket].socketDelegate = nil;
    [[ClientSocket shareSocket] disConn];
    [ClientSocket attempDealloc];

}

#pragma mark - ClientSocketDelegate
- (void)clientSocket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    NSLog(@"建立连接成功");
    [[ClientSocket shareSocket].socket readDataWithTimeout:-1 tag:101];
    [ClientSocket shareSocket].connectd = YES;
    // 开启定时器
    if ([ClientSocket shareSocket].connectTimer) {
        [[ClientSocket shareSocket].connectTimer invalidate];
        [ClientSocket shareSocket].connectTimer = nil;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [[ClientSocket shareSocket] addTimer];
    });
}

- (void)clientSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    
    if (100 == tag) {
        // 心跳
    }
    else if (101 == tag) {
        // conn
        NSString *text = [YZChatUtils convertDataToHexStr:data];
        NSString *printText = [NSString stringWithFormat:@"服务器返回--->%@",text];
        NSLog(@"%@",printText);
        char *str = (char *)[data bytes];
        unsigned char bts;
        unsigned long long r = varint_decode(str, 7, &bts);
        
        int btsLen = (int)bts;
        // 反序列化
        NSMutableString *realStr = [NSMutableString string];
        if (r * 2 <= text.length - btsLen * 2) {
            NSString *tempStr = [text substringWithRange:NSMakeRange(btsLen * 2, r * 2)];
            realStr = [NSMutableString stringWithString:tempStr];
            
            NSData *realData = [YZChatUtils dataFormHexString:realStr];
            ImMessage *p = [ImMessage parseFromData:realData error:nil];
            //            DLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                
                // 给服务器发送ack,确认收到离线消息
                [[ClientSocket shareSocket] doAck:p.messageId];
            };
        }
    } else {
        _allSize += data.length;
        [_allData appendData:data];
        NSLog(@"_allsize--->%ld",_allSize);
        [self readBytes:data];
    }
    
    
    // 继续接收数据
    [[ClientSocket shareSocket].socket readDataWithTimeout:-1 tag:0];
}

- (void)readBytes:(NSData *)data {
    // 过滤心跳包
    NSString *text = [YZChatUtils convertDataToHexStr:data];
    if ([self isDelayHeartRecData:text]) {
        NSLog(@"接收心跳OK");
        [ClientSocket shareSocket].receHearDt = [NSDate date];
        NSTimeInterval interlTimer = [[ClientSocket shareSocket].receHearDt timeIntervalSinceDate:[ClientSocket shareSocket].sendHeartDt];
        if (interlTimer < HEART_TIME * 2) {
            interlTimer = 0;
            return;
        } else {
            // 连接失效，客户端关闭socket并重新建立连接
            NSLog(@"心跳失效，重新连接");
            
            // 重新连接
            dispatch_async(dispatch_get_main_queue(), ^{
                [[ClientSocket shareSocket] autoConnection];
            });
        }
    }
    
    // 如果待读字节数大于0
    if (_bufferSize > 0) {
        if (data.length < _bufferSize) {
            // 继续读
            _bufferSize = _bufferSize - data.length;
            [_buffer appendData:data];
        } else {
            NSData *temp = [data subdataWithRange:NSMakeRange(0, _bufferSize)];
            [_buffer appendData:temp];
            // 解析数据
            ImMessage *p = [ImMessage parseFromData:_buffer error:nil];
            NSLog(@"p>>>%@",p);
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                // 刷新页面
                [self accpetMessage:p];
            };
            
            // 剩余的再处理一次
            NSUInteger leftInt = data.length - _bufferSize;
            if (leftInt > 0) {
                NSData *leftData = [data subdataWithRange:NSMakeRange(_bufferSize, data.length - _bufferSize)];
                
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
                
                [self readBytes:leftData];
            } else {
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
            }
        }
    } else {
        char *str = (char *)[data bytes];
        unsigned char bts;
        unsigned long long r = varint_decode(str, 7, &bts);
        int btsLen = (int)bts;
        if (data.length < r + btsLen) {
            _bufferSize = r - data.length + btsLen;
            NSData *appData = [data subdataWithRange:NSMakeRange(btsLen, data.length - btsLen)];
            [_buffer appendData:appData];
        } else if (data.length == r + btsLen) {
            // 解析数据
            NSData *tempData = [data subdataWithRange:NSMakeRange(btsLen, r)];
            ImMessage *p = [ImMessage parseFromData:tempData error:nil];
            NSLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                
                // 刷新页面
                [self accpetMessage:p];
                
                
            };
        } else if (data.length > r + btsLen) {
            // 粘包
            NSData *appData = [data subdataWithRange:NSMakeRange(r + btsLen + btsLen, data.length - r - btsLen - btsLen)];
            [_buffer appendData:appData];
            NSData *dealData = [data subdataWithRange:NSMakeRange(btsLen, r)];
            
            // 解析数据
            ImMessage *p = [ImMessage parseFromData:dealData error:nil];
            NSLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                // 刷新页面
                [self accpetMessage:p];
            };
            
            // 剩余的再处理一次
            NSUInteger leftInt = data.length - btsLen - r;
            if (leftInt > 0) {
                NSData *leftData = [data subdataWithRange:NSMakeRange(btsLen + r, data.length - btsLen - r)];
                
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
                
                [self readBytes:leftData];
            } else {
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
            }
        }
    }
}

#pragma mark - 发送消息核心方法
- (void)doSendMessage:(NSData *)dMessage
            mediaType:(NSString *)mediaType
          messageType:(NSString *)messType{
    
    // 消息
    ImMessage *_mess = [YZChatUtils createMessage:@"YZIMP"
                                          version:@"1.0"
                                           userId:[YZUser sharedInstance].uid
                                        userToken:[YZUser sharedInstance].token
                                        messageId:1
                                      messageType:messType
                                      messageTime:[[YZChatUtils getTimeInterval2] integerValue] termType:@"iOS"
                                         receiver:self.targetId
                                           sender:[YZUser sharedInstance].uid
                                    ctrlMessageId:0
                                        mediaType:mediaType
                                         playload:dMessage];
    NSLog(@"p>>>%@",_mess);
    
    // 序列化
    NSData *allData = [_mess data];
    
    // 消息长度
    unsigned long long number = [allData length];
    char* str = calloc(7, sizeof(char));
    unsigned char bts;
    varint_encode(number, str, 7, &bts);
    NSData *headVarint = [NSData dataWithBytes:str length:bts];
    NSLog(@"headVarint>>>%@",headVarint);
    free(str);
    
    // 总个消息
    NSMutableData *totalData = [NSMutableData dataWithData:headVarint];
    [totalData appendData:allData];
    
    [[ClientSocket shareSocket].socket writeData:totalData withTimeout:-1 tag:0];
    
}

- (void)accpetMessage:(ImMessage *)p {
}


#pragma mark - lazy load
- (UITableView *)applyFriendTable {
    
    if (!_applyFriendTable) {
        CGRect appleTableFrame = CGRectMake(0, 0, kWidth, kHeight);
        _applyFriendTable = [[UITableView alloc] initWithFrame:appleTableFrame style:UITableViewStyleGrouped];
        _applyFriendTable.delegate = self;
        _applyFriendTable.dataSource = self;
        
        [_applyFriendTable registerClass:[YZFriendApplyCell class] forCellReuseIdentifier:flagCell];
    }
    
    return _applyFriendTable;
}

- (YZFriendVM *)friendVM {
    if (!_friendVM) {
        _friendVM = [YZFriendVM new];
    }
    
    return _friendVM;
}


#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    YZFriendApplyCell *applyCell = [tableView dequeueReusableCellWithIdentifier:flagCell];
    applyCell.inputBlock = ^(NSString *str) {
        self.inpuString = str;
    };
    
    return applyCell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 44;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return @"你需要发送验证，等待对方同意";
}

#pragma mark - event
- (void)sendApply:(UIButton *)sender{
    // 检验输入
    if (kObjectIsEmpty(self.inpuString)) {
        [SVProgressHUD showInfoWithStatus:@"请输入验证申请"];
        return;
    }
    
    // 判断是否是好友关系
    [self performSelector:@selector(friendRelationRequest:)
               withObject:self.targetId afterDelay:0.1];
    
}

#pragma mark - request
- (void)friendRelationRequest:(NSString *)targetId {
    @weakify(self)
    [[self.friendVM isFriend:targetId] subscribeNext:^(id  _Nullable x) {
        NSLog(@"是否好友关系------>%@",x);
        
        @strongify(self);
        
        if (![x boolValue]) {
            
            NSDictionary *friendReqDic = @{@"action": @"addRequest",@"message":self.inpuString};
            NSData *sentData = [NSJSONSerialization dataWithJSONObject:friendReqDic options:NSJSONWritingPrettyPrinted error:nil];
            
            [self doSendMessage:sentData mediaType:@"application/json" messageType:@"friend"];
            
            [SVProgressHUD showSuccessWithStatus:@"发送成功"];
            
        } else {
            [SVProgressHUD showInfoWithStatus:@"您们已经是好友关系"];
        }
        
    } completed:^{
        
    }];
}

#pragma mark - private
// 处理接收服务端返回心跳延迟的情况，心跳返回：100000
- (BOOL)isDelayHeartRecData:(NSString *)recStr{
    BOOL isDelay = NO;
    NSUInteger num = 0;
    NSUInteger len = recStr.length;
    num = [YZChatUtils cauculateTimer:recStr subStr:@"100000"];
    if (num > 0) {
        if (num * 6 == len) {
            isDelay = YES;
        }
    }
    
    return isDelay;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
